﻿#region Includes
using System;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using Color4 = OpenTK.Graphics.Color4;
using GingerGL.Math;
using GingerGL.Graphics;
#endregion

namespace GingerGL.Utilities
{
    /// <summary>
    /// List of functions to create demo objects
    /// </summary>
    static public class Shapes
    {
        /// <summary>
        /// Build Basic Cube
        /// </summary>
        /// <param name="width">Width of Sides</param>
        static public Mesh Cube(float width)
        {
            Mesh m = new Mesh(BeginMode.Triangles, VertexUsage.Position | VertexUsage.Color | VertexUsage.Normal);
            
            float L = (0.5f * width);
            float n = 0.57735f;
            for (int ndex = 0; ndex < 36; ndex++)
                m.Buffer.IndexBuffer.Write(ndex);

            // Back
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(L, -L, -L),   new Vector3(n, -n, -n), new Vector2(0.0f, 0.0f), Color4.Red));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(-L, -L, -L),  new Vector3(-n, -n, -n),new Vector2(1.0f, 0.0f), Color4.Black));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(L, L, -L),    new Vector3(n, n, -n),  new Vector2(0.0f, 1.0f), Color4.Yellow));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(L, L, -L),    new Vector3(n, n, -n),  new Vector2(0.0f, 1.0f), Color4.Yellow));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(-L, -L, -L),  new Vector3(-n, -n, -n),new Vector2(1.0f, 0.0f), Color4.Black));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(-L, L, -L),   new Vector3(-n, n, -n), new Vector2(1.0f, 1.0f), Color4.Green));

            // Bottom

            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(-L, -L, L),   new Vector3(-n, -n, n), new Vector2(0.0f, 1.0f), Color4.Blue));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(-L, -L, -L),  new Vector3(-n, -n, -n),new Vector2(0.0f, 0.0f), Color4.Black));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(L, -L, L),    new Vector3(n, -n, n),  new Vector2(1.0f, 1.0f), Color4.Fuchsia));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(L, -L, L),    new Vector3(n, -n, n),  new Vector2(1.0f, 1.0f), Color4.Fuchsia));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(-L, -L, -L),  new Vector3(-n, -n, -n),new Vector2(0.0f, 0.0f), Color4.Black));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(L, -L, -L),   new Vector3(n, -n, -n), new Vector2(1.0f, 0.0f), Color4.Red));

            // Left

            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(-L, -L, -L),  new Vector3(-n, -n, -n),new Vector2(0.0f, 0.0f), Color4.Black));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(-L, -L, L),   new Vector3(-n, -n, n), new Vector2(1.0f, 0.0f), Color4.Blue));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(-L, L, -L),   new Vector3(-n, n, -n), new Vector2(0.0f, 1.0f), Color4.Green));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(-L, L, -L),   new Vector3(-n, n, -n), new Vector2(0.0f, 1.0f), Color4.Green));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(-L, -L, L),   new Vector3(-n, -n, n), new Vector2(1.0f, 0.0f), Color4.Blue));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(-L, L, L),    new Vector3(-n, n, n),  new Vector2(1.0f, 1.0f), Color4.Teal));

            // Right

            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(L, -L, L),    new Vector3(n, -n, n),  new Vector2(0.0f, 0.0f), Color4.Fuchsia));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(L, -L, -L),   new Vector3(n, -n, -n), new Vector2(1.0f, 0.0f), Color4.Red));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(L, L, L),     new Vector3(n, n, n),   new Vector2(0.0f, 1.0f), Color4.White));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(L, L, L),     new Vector3(n, n, n),   new Vector2(0.0f, 1.0f), Color4.White));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(L, -L, -L),   new Vector3(n, -n, -n), new Vector2(1.0f, 0.0f), Color4.Red));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(L, L, -L),    new Vector3(n, n, -n),  new Vector2(1.0f, 1.0f), Color4.Yellow));

            // Top

            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(L, L, -L),    new Vector3(n, n, -n),  new Vector2(1.0f, 1.0f), Color4.Yellow));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(-L, L, -L),   new Vector3(-n, n, -n), new Vector2(0.0f, 1.0f), Color4.Green));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(L, L, L),     new Vector3(n, n, n),   new Vector2(1.0f, 0.0f), Color4.White));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(L, L, L),     new Vector3(n, n, n),   new Vector2(1.0f, 0.0f), Color4.White));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(-L, L, -L),   new Vector3(-n, n, -n), new Vector2(0.0f, 1.0f), Color4.Green));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(-L, L, L),    new Vector3(-n, n, n),  new Vector2(0.0f, 0.0f), Color4.Teal));

            // Front

            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(-L, -L, L),   new Vector3(-n, -n, n), new Vector2(0.0f, 0.0f), Color4.Blue));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(L, -L, L),    new Vector3(n, -n, n),  new Vector2(1.0f, 0.0f), Color4.Fuchsia));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(-L, L, L),    new Vector3(-n, n, n),  new Vector2(0.0f, 1.0f), Color4.Teal));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(-L, L, L),    new Vector3(-n, n, n),  new Vector2(0.0f, 1.0f), Color4.Teal));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(L, -L, L),    new Vector3(n, -n, n),  new Vector2(1.0f, 0.0f), Color4.Fuchsia));
            m.Buffer.VertexBuffer.Write(new Vertex(new Vector3(L, L, L),     new Vector3(n, n, n),   new Vector2(1.0f, 1.0f), Color4.White));

            m.Buffer.Commit();

            return m;
        }
    }
}
